#include "..\\code\\dataStruct.h"
#include "..\\code\\common.h"

extern void reactorCurrentDiffRelay(Device *device);

extern void reactorOverCurrentRelay(Device *device);

extern void reactorZeroCurrentRelay(Device *device);

extern void reactorTrip(Device *device);


void reactor(Device *device) {

    // 误码生成替换
    errorDataOperation(device);

    // 如果当前相量数据错误
    if (isDataValid(device, 0) == 0) return;

    // 将采样值存入瞬时值数组
    sample2inst(device);

    // 瞬时值滤波后存入并更新滤波后数组
    dataFilter(device);

    // 利用滤波后数据计算12通道相量, 存入phasor数组
    toPhasor(device);


    if (device->time < STABLE_TIME) {
        // 等待仿真进入稳定状态
        return;
    }

    // 1.差动保护: 纵差差动速断保护、比率差动
    reactorCurrentDiffRelay(device);
    // 2.过流保护
    reactorOverCurrentRelay(device);
    // 3.零序过流保护
    reactorZeroCurrentRelay(device);
    // 4.保护动作出口
    reactorTrip(device);

}


/**
 * 电流差动保护
 * 任意一相差动动作, 三相动作出口
 * @param device
 */
void reactorCurrentDiffRelay(Device *device) {

    if (device->reactor.currentDiffEnable == 0) return;
    // 保护动作后不再判定, 锁存动作结果
    if (device->reactor.currentDiffTripFlag == 1) return;

    int phase = 0;
    for (phase = 0; phase < 3; phase++) {
        Phasor *Ip1 = device->phasor + 3;
        Phasor *Ip2 = device->phasor + 9;
        double Id, Ir, Ie = 0;

        // 差动电流
        Id = phasorAbs(phasorAdd(Ip1[phase], Ip2[phase]));

        // 制动电流
        Ir = 0.5 * phasorAbs(phasorSub(Ip1[phase], Ip2[phase]));

        // 相电流
        Ie = phasorAbs(Ip1[phase]);

        // 启动
        if (Id > device->reactor.currentDiffFastSetValue) {
            device->reactor.currentDiffStartFlag = 1;
            device->reactor.currentDiffStartTime = device->time;
            writePlainLog(device, "差动速断保护启动");
            break;
        } else {
            // 按照比率差动保护判据动作
            if ((Ir <= Ie && Id > device->reactor.currentDiffStartValue) ||
                (Ir > Ie && Id > 0.5 * (Ir - Ie) + device->reactor.currentDiffStartValue)) {
                device->reactor.currentDiffStartFlag = 1;
                device->reactor.currentDiffStartTime = device->time;
                writePlainLog(device, "电抗器低值比率差动保护启动");
                break;
            } else if (Id > 1.2 * Ie && Id > Ir) {
                device->reactor.currentDiffStartFlag = 1;
                device->reactor.currentDiffStartTime = device->time;
                writePlainLog(device, "电抗器高值比率差动保护启动");
                break;
            }
        }

        // 动作出口
        if (device->reactor.currentDiffStartFlag && device->time - device->reactor.currentDiffStartTime > HALF_CYCLE) {
            if (Id > device->reactor.currentDiffFastSetValue) {
                device->reactor.currentDiffTripFlag = 1;
                writePlainLog(device, "差动速断保护动作");
                break;
            } else {
                // 按照比率差动保护判据动作
                if ((Ir <= Ie && Id > device->reactor.currentDiffStartValue) ||
                    (Ir > Ie && Id > 0.5 * (Ir - Ie) + device->reactor.currentDiffStartValue)) {
                    device->reactor.currentDiffTripFlag = 1;
                    writePlainLog(device, "电抗器低值比率差动保护动作");
                    break;
                } else if (Id > 1.2 * Ie && Id > Ir) {
                    device->reactor.currentDiffTripFlag = 1;
                    writePlainLog(device, "电抗器高值比率差动保护动作");
                    break;
                }
            }
        }
    }
}


/**
 * 过电流保护, 两段式
 * @param device
 */
void reactorOverCurrentRelay(Device *device) {
    if (device->reactor.overCurrentEnable == 0) return;
    // 保护动作后不再判定, 锁存动作结果
    if (device->reactor.overCurrentTripFlag == 1) return;


    int phase = 0;
    // I段启动判定
    for (phase = 0; phase < 3; phase++) {
        // 记录一次启动, 之后不再进入
        if (device->reactor.overCurrentOneStartFlag == 1) break;
        Phasor *Ip1 = device->phasor + 3;

        double currentAbs = phasorAbs(Ip1[phase]);

        if (currentAbs > device->reactor.overCurrentOneSetValue) {
            writePlainLog(device, "电抗器过电流I段保护启动");
            device->reactor.overCurrentOneStartFlag = 1;
            device->reactor.overCurrentOneStartTime = device->time;
            break;
        }
    }

    // I段动作判定
    for (phase = 0; phase < 3; phase++) {
        Phasor *Ip1 = device->phasor + 3;

        double currentAbs = phasorAbs(Ip1[phase]);
        // 满足三个条件, 保护已经启动; 电流大于整定值; 时间延时到达
        if (device->reactor.overCurrentOneStartFlag == 1 && currentAbs > device->reactor.overCurrentOneSetValue &&
            device->time > device->reactor.overCurrentOneStartTime + device->reactor.overCurrentOneTimeSetValue) {
            device->reactor.overCurrentTripFlag = 1;
            writeLogWithPhase(device, "电抗器%c相过电流I段保护动作", phase);
            break;
        }
    }

    // II段启动判定
    for (phase = 0; phase < 3; phase++) {
        // 记录一次启动, 之后不再进入
        if (device->reactor.overCurrentTwoStartFlag == 1) break;
        Phasor *Ip1 = device->phasor + 3;

        double currentAbs = phasorAbs(Ip1[phase]);

        if (currentAbs > device->reactor.overCurrentTwoSetValue) {
            writePlainLog(device, "电抗器过电流II段保护启动");
            device->reactor.overCurrentTwoStartFlag = 1;
            device->reactor.overCurrentTwoStartTime = device->time;
            break;
        }
    }

    // II段动作判定
    for (phase = 0; phase < 3; phase++) {
        Phasor *Ip1 = device->phasor + 3;

        double currentAbs = phasorAbs(Ip1[phase]);
        // 满足三个条件, 保护已经启动; 电流大于整定值; 时间延时到达
        if (device->reactor.overCurrentTwoStartFlag == 1 && currentAbs > device->reactor.overCurrentTwoSetValue &&
            device->time > device->reactor.overCurrentTwoStartTime + device->reactor.overCurrentTwoTimeSetValue) {
            device->reactor.overCurrentTripFlag = 1;
            writeLogWithPhase(device, "电抗器%c相过电流II段保护动作", phase);
            break;
        }
    }
}

/**
 * 零序过电流保护
 */
void reactorZeroCurrentRelay(Device *device) {
    if (device->reactor.zeroCurrentEnable == 0) return;
    // 保护动作后不再判定, 锁存动作结果
    if (device->reactor.zeroCurrentTripFlag == 1) return;


    int phase = 0;
    // 仅在没有启动的情况下才进行启动判据判别, 避免启动时间被覆盖
    if (device->reactor.zeroCurrentStartFlag == 0) {
        Phasor IpA = device->phasor[3];
        Phasor IpB = device->phasor[4];
        Phasor IpC = device->phasor[5];

        Phasor zeroPhase = phasorAdd(phasorAdd(IpA, IpB), IpC);
        double zeroAbs = phasorAbs(zeroPhase);

        if (zeroAbs > device->reactor.zeroCurrentSetValue) {
            writePlainLog(device, "电抗器零序过电流保护启动");
            device->reactor.zeroCurrentStartFlag = 1;
            device->reactor.zeroCurrentStartTime = device->time;
        }
    }

    // 如果零序保护已经启动才进入判别
    if (device->reactor.zeroCurrentStartFlag == 1) {
        Phasor IpA = device->phasor[3];
        Phasor IpB = device->phasor[4];
        Phasor IpC = device->phasor[5];

        Phasor zeroPhase = phasorAdd(phasorAdd(IpA, IpB), IpC);
        double zeroAbs = phasorAbs(zeroPhase);
        // 三条件, 时间+条件+(启动)
        if (device->time > device->reactor.zeroCurrentStartTime + device->reactor.zeroCurrentTimeSetValue &&
            zeroAbs > device->reactor.zeroCurrentSetValue) {
            device->reactor.zeroCurrentTripFlag = 1;
            writePlainLog(device, "电抗器零序过电流保护动作");
        }
    }
}


/**
 * 动作出口判定
 */
void reactorTrip(Device *device) {
    if (device->reactor.currentDiffTripFlag == 1 || device->reactor.overCurrentTripFlag == 1 ||
        device->reactor.zeroCurrentTripFlag == 1) {
        int i = 0;
        for (i = 0; i < 3; i++) {
            device->outRes[i] = 1;
        }
        writeLog(device, "电抗器保护动作出口");
    }
}


